Material and idea Source: https://github.com/bupaverse

1. Scenario 1

1.1 Read data

sc1_data <- read.csv("C:/Users/nikol/Downloads/scenario1.csv", sep=";")

1.2 Analyze data structure

head(sc1_data)

1.3 Data wrangling

sc1_activitylog <- sc1_data %>%
    # rename timestamp variables appropriately
    dplyr::rename(start = activity_started, 
           complete = activity_ended) %>%
    # convert timestamps to 
    convert_timestamps(columns = c("start", "complete"), format = ymd_hms) %>%
    activitylog(case_id = "patient",
                activity_id = "handling",
                resource_id = "employee",
                timestamps = c("start", "complete"))

1.4 Data visualization

1.4.1 Processmap, frequency

#frequency: absolute, absolute_case, relative, relative_case
print(process_map(sc1_activitylog, type=frequency("absolute")))
NULL

1.4.2 Processmap, performance

#performance: median/mean, "years"/"semesters"/"quarters"/"months"/"weeks"/"days"/"hours"/"mins"/"secs"
print(process_map(sc1_activitylog, type=performance(median,"secs")))
NULL

1.4.3 Ressourcemap, frequency

resource_map(sc1_activitylog, type=frequency("absolute"))

1.4.5 Ressourcemap, performance

resource_map(sc1_activitylog, type=performance(median,"secs"))

2. Scenario 2

2.1 Read data

sc2_data <- read.csv("C:/Users/nikol/Downloads/scenario2.csv", sep=";")

2.2 Analyze data structure

head(sc2_data)

2.3 Data wrangling

sc2_data %>%
    # recode lifecycle variable appropriately
    dplyr::mutate(registration_type = forcats::fct_recode(registration_type, 
                                                          "start" = "started",
                                                          "complete" = "completed")) %>%
    convert_timestamps(columns = "time", format = ymd_hms) %>%
    eventlog(case_id = "patient",
             activity_id = "handling",
             activity_instance_id = "handling_id",
             lifecycle_id = "registration_type",
             timestamp = "time",
             resource_id = "employee") %>%
    to_activitylog() -> sc2_activitylog

sc2_activitylog
# Log of 10 events consisting of:
1 trace 
1 case 
5 instances of 5 activities 
5 resources 
Events occurred from 2018-09-20 17:16:02 until 2021-09-20 17:03:14 
 
# Variables were mapped as follows:
Case identifier:        patient 
Activity identifier:        handling 
Resource identifier:        employee 
Timestamps:     start, complete 

2.4 Data visualization

2.4.1 Processmap, frequency

#frequency: absolute, absolute_case, relative, relative_case
print(process_map(sc2_activitylog, type=frequency("absolute")))
NULL

2.4.2 Processmap, performance

#performance: median/mean, "years"/"semesters"/"quarters"/"months"/"weeks"/"days"/"hours"/"mins"/"secs"
print(process_map(sc2_activitylog, type=performance(median,"secs")))
NULL

2.4.3 Ressourcemap, frequency

resource_map(sc2_activitylog, type=frequency("absolute"))

2.4.4 Ressourcemap, performance

resource_map(sc2_activitylog, type=performance(median,"secs"))

3. Scenario 3

3.1 Read data

sc3_data <- read.csv("C:/Users/nikol/Downloads/scenario3.csv", sep=";")

3.2 Analyze data structure

head(sc3_data)

3.3 Data wrangling

sc3_activitylog <- sc3_data %>%
    # recode lifecycle variable appropriately
    dplyr::mutate(registration_type = forcats::fct_recode(registration_type, 
                                                          "start" = "started",
                                                          "complete" = "completed")) %>%
    convert_timestamps(columns = "time", format = ymd_hms) %>%
    eventlog(case_id = "patient",
                activity_id = "handling",
                activity_instance_id = "handling_id",
                lifecycle_id = "registration_type",
                timestamp = "time",
                resource_id = "employee") 
G2;H2;Warningh in validate_eventlog(eventlog) :
  The following activity instances are connected to more than one resource: 125,625,1060,1297,1859,2354g
sc3_activitylog
# Log of 12 events consisting of:
1 trace 
1 case 
6 instances of 6 activities 
6 resources 
Events occurred from 2004-05-20 17:21:29 until 2012-05-20 17:21:59 
 
# Variables were mapped as follows:
Case identifier:        patient 
Activity identifier:        handling 
Resource identifier:        employee 
Activity instance identifier:   handling_id 
Timestamp:          time 
Lifecycle transition:       registration_type 

3.4 Data visualization

3.4.1 Processmap, frequency

#frequency: absolute, absolute_case, relative, relative_case
print(process_map(sc3_activitylog, type=frequency("absolute")))
NULL

3.4.2 Processmap, performance

#performance: median/mean, "years"/"semesters"/"quarters"/"months"/"weeks"/"days"/"hours"/"mins"/"secs"
print(process_map(sc3_activitylog, type=performance(median,"secs")))
NULL

3.4.3 Ressourcemap, frequency

resource_map(sc3_activitylog, type=frequency("absolute"))

3.4.4 Ressourcemap, performance

resource_map(sc3_activitylog, type=performance(median,"secs"))

4. General presentation of the different possibilities regarding data visualization and analysis

4.1 Frequency maps

In the examples below, we will use a slightly filtered versions of the traffic_fines data set, which contains 95% of the cases that have the most frequent traces.

tmp <- traffic_fines %>%
    filter_trace_frequency(percentage = 0.95)

Absolute

In the examples below, I will use a slightly filtered version of the traffic_fines data set, which contains 95% of the cases with the most frequent traces.

tmp %>%
    process_map(frequency("absolute"))

Relative

In relative terms, I found that Payment represents 14.51% of the total activity instances. Additionally, I observed that in 94.66% of the cases where it occurred, it marked the end of the case. In the remaining 5.34% of cases, it was followed by another Payment.

tmp %>%
    process_map(frequency("relative"))

Relative case

Below, I found that Payment occurred in 46.21% of the cases. In 2.6% of the cases, I observed that a Payment activity was followed by another Payment.

tmp %>%
    process_map(frequency("relative-case"))

Relative consequent

Finally, the relative-consequent map shows what happens before activities. With respect to Payment, one can see that it was preceded by:

Create Fine (73.15%)
Add Penalty (21.51%)
Payment (5.34%)

Payment itself represents 14.51% of all activity executions.

tmp %>%
    process_map(frequency("relative-consequent"))

4.2 Performance profile

Instead of using frequencies, I can also use process maps to visualize the performance of the process, by using performance() to configure the map instead of frequency().

There are three different parameters specific to the performance() configuration that I can adjust: the aggregation function, the time units, and the flow time type.

patients %>%
    process_map(performance())

Aggregation function

The FUN argument specifies the aggregation function I want to apply on the processing time (e.g., min, max, mean, median, etc.). By default, the mean durations are shown, but I can adjust this to the maximum, for example.

patients %>%
    process_map(performance(FUN = max))
G2;H2;Warnungh: There was 1 warning in `summarize()`.
ℹ In argument: `label = do.call(...)`.
ℹ In group 10: `ACTIVITY_CLASSIFIER_ = NA` and `from_id = NA`.
Caused by warning in `type()`:
! kein nicht-fehlendes Argument für max; gebe -Inf zurückg
G2;H2;Warnungh: There were 2 warnings in `summarize()`.
The first warning was:
ℹ In argument: `value = do.call(...)`.
ℹ In group 1: `ACTIVITY_CLASSIFIER_ = "ARTIFICIAL_END"`, `next_act = NA`, `from_id = 1`, `to_id = NA`.
Caused by warning in `type()`:
! kein nicht-fehlendes Argument für max; gebe -Inf zurück
ℹ Run ]8;;ide:run:dplyr::last_dplyr_]8;;ide:run:warnings()warnings()]8;;dplyr::last_dplyr_]8;;ide:run:warnings()warnings()]8;;]8;; to see the 1 remaining warning.g

Any function that takes a numerical vector and returns a single value can be used. For example, if I want to show the 0.90 percentile, I can use that function.

p90 <- function(x, ...) {
    quantile(x, probs = 0.9, ...)
}

patients %>%
    process_map(performance(FUN = p90))

Time units

The units argument allows me to specify the time units I want to use.

For example in days:

patients %>%
    process_map(performance(mean, "days"))

For example in hours:

patients %>%
    process_map(performance(mean, "hours"))

4.3 Advanced maps

Combining different profiles

I can differentiate the profile used for nodes and edges by using the type_nodes and type_edges attributes instead of the type argument. This way, I can combine information about frequencies, performance, or any other value in the same graph.

patients %>%
    process_map(type_nodes = frequency("relative_case"),
                type_edges = performance(mean))

Adding secondary information

I can add a second layer of information to both nodes and edges.

patients %>%
    process_map(type = frequency("relative_case"),
                sec = frequency("absolute"))

I can differentiate both primary and secondary layers between nodes and edges.

patients %>%
    process_map(type_nodes =  frequency("relative_case"),
                type_edges = performance(units = "hours"),
                sec_nodes = frequency("absolute"),
                sec_edges = performance(FUN = max, units = "hours"))
G2;H2;Warnungh: There were 2 warnings in `summarize()`.
The first warning was:
ℹ In argument: `value = do.call(...)`.
ℹ In group 1: `ACTIVITY_CLASSIFIER_ = "ARTIFICIAL_END"`, `next_act = NA`, `from_id = 1`, `to_id = NA`.
Caused by warning in `type()`:
! kein nicht-fehlendes Argument für max; gebe -Inf zurück
ℹ Run ]8;;ide:run:dplyr::last_dplyr_]8;;ide:run:warnings()warnings()]8;;dplyr::last_dplyr_]8;;ide:run:warnings()warnings()]8;;]8;; to see the 1 remaining warning.g

Customizing colors

Both frequency() and performance() have the arguments color_scale and color_edges to customize the colors in the process map:

  • color_scale: I can set the color scale to fill the nodes. It can be any of the scales in RColorBrewer::brewer.pal.info. By default, it’s set to PuBu (for frequency) or Reds (for performance).
  • color_edges: I can apply any single color to the arrows, such as a named color, hex-code, or a result of rgb. By default, it’s set to dodgerblue4 (for frequency) or red4 (for performance).

Configuring the colors can be useful for harmonizing the process map aesthetics when using different layers for nodes and edges.

patients %>%
    process_map(type_nodes = frequency("relative_case", color_scale = "PuBu"),
                type_edges = performance(mean, color_edges = "dodgerblue4"))

4.4 Animate Maps

Here, I use the patients’ event log provided by the eventdataR package.

Here’s a basic animation with static color and token size:

animate_process(patients)

I can change the default token color, size, or image as follows:

animate_process(patients, mapping = token_aes(size = token_scale(12), shape = "rect"))

Different token color.

animate_process(patients, mapping = token_aes(color = token_scale("red")))

Some combinations of options as mentioned above.

animate_process(patients, mode = "relative", jitter = 10, legend = "color",
  mapping = token_aes(color = token_scale("employee", 
    scale = "ordinal", 
    range = RColorBrewer::brewer.pal(7, "Paired"))))

4.5 Process Matrix

Absolute

traffic_fines %>%
    process_matrix(frequency("absolute")) 

The Absolute Process Matrix is a tool I use to visualize the frequency of transitions between activities in a process, where the matrix displays the count of occurrences for each pair of activities.

traffic_fines %>%
    process_matrix(frequency("absolute")) %>%
    plot()

Relative-case

traffic_fines %>%
    process_matrix(frequency("relative-case")) 

The Relative-case Process Matrix is a tool I use to visualize the transitions between activities in a process, where the matrix shows the frequency of each transition relative to the total number of cases, providing insights into the proportion of cases that follow specific activity paths.

traffic_fines %>%
    process_matrix(frequency("relative-case")) %>%
    plot()

Relative-antecedent

traffic_fines %>%
    process_matrix(frequency("relative-antecedent")) 

The Relative-antecedent Process Matrix is a tool I use to visualize the frequency of transitions between activities in a process, where it shows how often each activity is preceded by specific antecedent activities, expressed relative to the total number of cases.

traffic_fines %>%
    process_matrix(frequency("relative-antecedent")) %>%
    plot()

Relative-consequent

traffic_fines %>%
    process_matrix(frequency("relative-consequent")) 

The Relative-consequent Process Matrix is a tool I use to visualize the frequency of transitions between activities in a process, where it shows how often each activity is followed by specific subsequent activities, expressed relative to the total number of cases.

traffic_fines %>%
    process_matrix(frequency("relative-consequent")) %>%
    plot()

Performance

traffic_fines %>%
    process_matrix(performance(FUN = mean, units = "weeks")) 

The Performance Process Matrix is a tool I use to visualize not only the frequency of activity transitions but also the performance metrics, such as the time taken for each transition, allowing me to analyze how efficiently different process paths are performed.

traffic_fines %>%
    process_matrix(performance(FUN = mean, units = "weeks"))  %>%
    plot()

Summary

The various versions of the process matrices provide different perspectives on the transitions between activities in a process.

  • Absolute Process Matrix displays the raw frequency of transitions between activities, showing the total count of occurrences for each pair of activities, regardless of the number of cases.

  • Relative-case Process Matrix provides a normalized view by showing the frequency of transitions as a proportion of the total number of cases. This allows for better insight into the relative occurrence of each activity pair in the overall process.

  • Relative-antecedent Process Matrix focuses on the activities that precede others. It shows the frequency of transitions where each activity is preceded by specific antecedent activities, normalized by the total number of cases.

  • Relative-consequent Process Matrix looks at the activities that follow others. It shows the frequency of transitions where each activity is followed by specific consequent activities, again expressed relative to the total number of cases.

  • Performance Process Matrix combines frequency analysis with performance metrics, displaying how long each transition takes and highlighting the efficiency of different paths in the process.

In summary, while the Absolute Process Matrix gives raw counts, the relative matrices provide normalized insights into the relationships between activities, and the Performance Process Matrix adds a layer of analysis on the time or efficiency of transitions.

4.6 Dotted Chart

Absolute

The Absolute Dotted Chart is a visualization tool I use to display the frequency of activity occurrences in a process, where each activity is represented by a dot, and the total count of each activity is shown as the number of dots, providing a clear view of activity distribution.

sepsis %>%
    dotted_chart(x = "absolute")

The Absolute Dotted Chart with the sort = “end” option arranges the activities in the process based on their occurrence at the end of the cases, allowing me to focus on the final activities and their frequencies in the process flow.

sepsis %>%
    dotted_chart(x = "absolute", sort = "end")

Relative

The Relative Dotted Chart visualizes the relative frequency of activity occurrences in a process, normalizing the data to show each activity’s proportion in relation to the total number of cases. Each dot represents an activity, and the number of dots reflects its relative frequency, helping to compare the prevalence of different activities in the process.

sepsis %>%
    dotted_chart(x = "relative")

Relative week 1

The relative_week Dotted Chart displays the relative frequency of activity occurrences week by week, allowing me to analyze how the prevalence of activities changes over time on a weekly basis with ggplot2 colors.

sepsis %>%
    dotted_chart(x = "relative_week",
                 scale_color = ggplot2::scale_color_discrete)

Relative day

The relative_day Dotted Chart shows the relative frequency of activity occurrences on a daily basis, helping me analyze how the distribution of activities varies from day to day.

sepsis %>%
    dotted_chart(x = "relative_day")

Relative week 2

The relative_week Dotted Chart displays the relative frequency of activity occurrences week by week, allowing me to analyze how the prevalence of activities changes over time on a weekly basis.

sepsis %>%
    dotted_chart(x = "relative_week")

4.7 Trace explorer

The trace_explorer() function allows me to explore individual case traces within a process, providing insights into the sequence of activities and helping to identify patterns or anomalies in specific case executions.

sepsis %>%
    trace_explorer()
G2;H2;Warnungh: No `coverage` or `n_traces` set.
! Defaulting to `coverage` = 0.2 for `type` = "frequent" traces.g

The code sepsis %>% trace_explorer(coverage = 0.15) allows me to explore the traces in the sepsis dataset, focusing on cases where at least 15% of the activities are covered, helping to analyze more representative process paths.

sepsis %>%
    trace_explorer(coverage = 0.15)

The code sepsis %>% trace_explorer(n_traces = 10) enables me to explore the first 10 traces in the sepsis dataset, providing a closer look at a subset of the process flows for detailed analysis.

sepsis %>%
    trace_explorer(n_traces = 10)

The code sepsis %>% trace_explorer(n_traces = 10, type = "infrequent") allows me to explore the 10 least frequent traces in the sepsis dataset, helping to analyze rare or unusual process paths.

sepsis %>%
    trace_explorer(n_traces = 10, type = "infrequent")

The code sepsis %>% trace_explorer(n_traces = 10, coverage_labels = c("cumulative", "relative")) enables me to explore the first 10 traces in the sepsis dataset, displaying both cumulative and relative coverage labels to better understand the distribution of activity occurrences.

sepsis %>%
    trace_explorer(n_traces = 10,
                   coverage_labels = c("cumulative", "relative"))

The code sepsis %>% trace_explorer(n_traces = 10, label_size = 4) allows me to explore the first 10 traces in the sepsis dataset while adjusting the label size to 4, making the trace labels more readable for better analysis.

sepsis %>%
    trace_explorer(n_traces = 10, label_size = 4)

The code sepsis %>% trace_explorer(n_traces = 10, show_labels = FALSE) allows me to explore the first 10 traces in the sepsis dataset without displaying the labels, providing a cleaner view of the trace sequences.

sepsis %>%
    trace_explorer(n_traces = 10, 
                   show_labels = FALSE)

The code sepsis %>% trace_explorer(n_traces = 10, abbreviate = FALSE) allows me to explore the first 10 traces in the sepsis dataset without abbreviating the activity labels, providing a full view of the trace details.

sepsis %>%
    trace_explorer(n_traces = 10, abbreviate = FALSE)

The code sepsis %>% trace_explorer(n_traces = 10, scale_fill = ggplot2::scale_fill_discrete) allows me to explore the first 10 traces in the sepsis dataset, applying a discrete color scale from ggplot2 to better differentiate the activity labels.

sepsis %>%
    trace_explorer(n_traces = 10,
                   scale_fill = ggplot2::scale_fill_discrete)

4.8 Performance Spectrum

The code traffic_fines %>% ps_detailed() generates a detailed process summary of the traffic_fines dataset, providing an in-depth view of the process flow and its characteristics.

traffic_fines %>%
    ps_detailed()

The code traffic_fines %>% ps_detailed(n_segments = 10) generates a detailed process summary of the traffic_fines dataset, displaying information for the first 10 segments of the process flow.

traffic_fines %>%
    ps_detailed(n_segments = 10)

The code traffic_fines %>% ps_detailed(classification = "resource") generates a detailed process summary of the traffic_fines dataset, focusing on the resource classification to provide insights into resource usage within the process.

traffic_fines %>%
    ps_detailed(classification = "resource")

The code traffic_fines %>% end_activities("case") %>% augment(traffic_fines, prefix = "end") %>% ps_detailed(classification = "end_activity") analyzes the end activities of the traffic_fines dataset, augments the data with information on these activities, and generates a detailed process summary focusing on the classification of end activities.

traffic_fines %>%
    end_activities("case") %>%
    augment(traffic_fines, prefix = "end") %>%
    ps_detailed(classification = "end_activity")

The code traffic_fines %>% end_activities("case") %>% augment(traffic_fines, prefix = "end") %>% group_by(end_activity) %>% ps_aggregated() analyzes the end activities of the traffic_fines dataset, augments the data with these activities, groups the data by end activity, and generates an aggregated process summary.

traffic_fines %>%
    end_activities("case") %>%
    augment(traffic_fines, prefix = "end") %>%
    group_by(end_activity) %>%
    ps_aggregated()

5. More Analytics

5.1 Control Flow

Activity Presence

The code patients %>% activity_presence() %>% plot visualizes the percentage of cases in which each activity is present in the patients dataset, providing an overview of activity presence without requiring a level argument.

patients %>% activity_presence() %>%
    plot

Activity frequency

The code patients %>% activity_frequency("activity") calculates the frequency of each activity in the patients dataset, providing insights into how often different activities occur within the process.

patients %>%
    activity_frequency("activity")

Start activities

The code patients %>% start_activities("resource-activity") identifies the starting activities in the patients dataset based on the resource-activity classification, helping to analyze the initial steps involving specific resources.

patients %>%
    start_activities("resource-activity")

End activities

The code patients %>% end_activities("resource-activity") identifies the end activities in the patients dataset based on the resource-activity classification, allowing me to analyze the final steps involving specific resources.

patients %>%
    end_activities("resource-activity")

Trace Coverage

The code patients %>% trace_coverage("trace") %>% plot() visualizes the coverage of different traces in the patients dataset, providing insights into how well the traces are represented within the data.

patients %>%
    trace_coverage("trace") %>%
    plot()

Trance length

The code patients %>% trace_length("log") %>% plot visualizes the distribution of trace lengths in the patients dataset, helping to analyze the variability in the number of activities within each trace.

patients %>%
    trace_length("log") %>%
    plot

5.2 Performance

Idle Time

The code patients %>% idle_time("resource", units = "days") calculates the idle time for each resource in the patients dataset, measuring the time in days when resources were not in use.

patients %>%
    idle_time("resource", units = "days")

The code patients %>% idle_time("resource", units = "days") %>% plot() visualizes the idle time of resources in the patients dataset, showing how many days each resource was inactive.

patients %>%
    idle_time("resource", units = "days") %>%
    plot()

Processing Time

The code patients %>% processing_time("activity") %>% plot visualizes the processing time for each activity in the patients dataset, providing insights into the duration of different activities within the process.

patients %>% 
    processing_time("activity") %>%
    plot

Throughput Time

The code patients %>% throughput_time("log") %>% plot() visualizes the throughput time in the patients dataset, displaying the time taken for cases to move through the entire process.

patients %>%
    throughput_time("log") %>%
    plot()

5.3 Organisational

Resource Frequency

The code patients %>% resource_frequency("resource") calculates the frequency of each resource in the patients dataset, showing how often different resources are utilized throughout the process.

patients %>%
    resource_frequency("resource")

Resource Involvment

The code patients %>% resource_involvement(level = "resource") %>% plot visualizes the involvement of each resource in the patients dataset, highlighting how frequently different resources participate in the process.

It this example it shows that only r1 and r2 are involved in all cases, r6 and r7 are involved in most of the cases, while the others are only involved in half of the cases, more or less.

patients %>%
    resource_involvement(level = "resource") %>% plot

Resource Specialization

The code patients %>% resource_specialisation("resource") analyzes the specialization of each resource in the patients dataset, showing the specific activities or tasks that each resource is most frequently involved in.

In the simple patients event log, each resource is performing exactly one activity, and is therefore 100% specialized.

patients %>%
    resource_specialisation("resource")

Handover-of-work network

The code patients %>% resource_map() generates a resource map of the patients dataset, visually displaying how resources are distributed and involved across different activities in the process.

patients %>%
    resource_map()

Resource precedence matrix

The code patients %>% resource_matrix() %>% plot() generates and visualizes a resource matrix for the patients dataset, showing the interactions between resources and activities within the process.

patients %>%
    resource_matrix() %>%
    plot()

5.4 Multi-dimensional

W O R K - I N - P R O G R E S S

LS0tDQp0aXRsZTogIlNBTVBMRSAtIEJ1c2luZXNzIFByb2Nlc3MgQW5hbHl0aWNzIC0gU0FNUExFIg0KYXV0aG9yOiBOaWtvbGEgUGF2aWENCmRhdGU6IDIwMjUNCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCk1hdGVyaWFsIGFuZCBpZGVhIFNvdXJjZTogaHR0cHM6Ly9naXRodWIuY29tL2J1cGF2ZXJzZQ0KDQojIDEuIFNjZW5hcmlvIDENCiMjIDEuMSBSZWFkIGRhdGENCmBgYHtyfQ0Kc2MxX2RhdGEgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL25pa29sL0Rvd25sb2Fkcy9zY2VuYXJpbzEuY3N2Iiwgc2VwPSI7IikNCmBgYA0KDQojIyAxLjIgQW5hbHl6ZSBkYXRhIHN0cnVjdHVyZQ0KYGBge3J9DQpoZWFkKHNjMV9kYXRhKQ0KYGBgDQojIyAxLjMgRGF0YSB3cmFuZ2xpbmcNCmBgYHtyfQ0Kc2MxX2FjdGl2aXR5bG9nIDwtIHNjMV9kYXRhICU+JQ0KICAgICMgcmVuYW1lIHRpbWVzdGFtcCB2YXJpYWJsZXMgYXBwcm9wcmlhdGVseQ0KICAgIGRwbHlyOjpyZW5hbWUoc3RhcnQgPSBhY3Rpdml0eV9zdGFydGVkLCANCiAgICAgICAgICAgY29tcGxldGUgPSBhY3Rpdml0eV9lbmRlZCkgJT4lDQogICAgIyBjb252ZXJ0IHRpbWVzdGFtcHMgdG8gDQogICAgY29udmVydF90aW1lc3RhbXBzKGNvbHVtbnMgPSBjKCJzdGFydCIsICJjb21wbGV0ZSIpLCBmb3JtYXQgPSB5bWRfaG1zKSAlPiUNCiAgICBhY3Rpdml0eWxvZyhjYXNlX2lkID0gInBhdGllbnQiLA0KICAgICAgICAgICAgICAgIGFjdGl2aXR5X2lkID0gImhhbmRsaW5nIiwNCiAgICAgICAgICAgICAgICByZXNvdXJjZV9pZCA9ICJlbXBsb3llZSIsDQogICAgICAgICAgICAgICAgdGltZXN0YW1wcyA9IGMoInN0YXJ0IiwgImNvbXBsZXRlIikpDQpgYGANCg0KIyMgMS40IERhdGEgdmlzdWFsaXphdGlvbg0KIyMgMS40LjEgUHJvY2Vzc21hcCwgZnJlcXVlbmN5DQpgYGB7cn0NCiNmcmVxdWVuY3k6IGFic29sdXRlLCBhYnNvbHV0ZV9jYXNlLCByZWxhdGl2ZSwgcmVsYXRpdmVfY2FzZQ0KcHJpbnQocHJvY2Vzc19tYXAoc2MxX2FjdGl2aXR5bG9nLCB0eXBlPWZyZXF1ZW5jeSgiYWJzb2x1dGUiKSkpDQpgYGANCg0KIyMgMS40LjIgUHJvY2Vzc21hcCwgcGVyZm9ybWFuY2UNCmBgYHtyfQ0KI3BlcmZvcm1hbmNlOiBtZWRpYW4vbWVhbiwgInllYXJzIi8ic2VtZXN0ZXJzIi8icXVhcnRlcnMiLyJtb250aHMiLyJ3ZWVrcyIvImRheXMiLyJob3VycyIvIm1pbnMiLyJzZWNzIg0KcHJpbnQocHJvY2Vzc19tYXAoc2MxX2FjdGl2aXR5bG9nLCB0eXBlPXBlcmZvcm1hbmNlKG1lZGlhbiwic2VjcyIpKSkNCmBgYA0KDQojIyAxLjQuMyBSZXNzb3VyY2VtYXAsIGZyZXF1ZW5jeQ0KYGBge3J9DQpyZXNvdXJjZV9tYXAoc2MxX2FjdGl2aXR5bG9nLCB0eXBlPWZyZXF1ZW5jeSgiYWJzb2x1dGUiKSkNCmBgYA0KDQojIyAxLjQuNSBSZXNzb3VyY2VtYXAsIHBlcmZvcm1hbmNlDQpgYGB7cn0NCnJlc291cmNlX21hcChzYzFfYWN0aXZpdHlsb2csIHR5cGU9cGVyZm9ybWFuY2UobWVkaWFuLCJzZWNzIikpDQpgYGANCg0KIyAyLiBTY2VuYXJpbyAyDQojIyAyLjEgUmVhZCBkYXRhDQpgYGB7cn0NCnNjMl9kYXRhIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9uaWtvbC9Eb3dubG9hZHMvc2NlbmFyaW8yLmNzdiIsIHNlcD0iOyIpDQpgYGANCg0KIyMgMi4yIEFuYWx5emUgZGF0YSBzdHJ1Y3R1cmUNCmBgYHtyfQ0KaGVhZChzYzJfZGF0YSkNCmBgYA0KDQojIyAyLjMgRGF0YSB3cmFuZ2xpbmcNCmBgYHtyfQ0Kc2MyX2RhdGEgJT4lDQogICAgIyByZWNvZGUgbGlmZWN5Y2xlIHZhcmlhYmxlIGFwcHJvcHJpYXRlbHkNCiAgICBkcGx5cjo6bXV0YXRlKHJlZ2lzdHJhdGlvbl90eXBlID0gZm9yY2F0czo6ZmN0X3JlY29kZShyZWdpc3RyYXRpb25fdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInN0YXJ0IiA9ICJzdGFydGVkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiY29tcGxldGUiID0gImNvbXBsZXRlZCIpKSAlPiUNCiAgICBjb252ZXJ0X3RpbWVzdGFtcHMoY29sdW1ucyA9ICJ0aW1lIiwgZm9ybWF0ID0geW1kX2htcykgJT4lDQogICAgZXZlbnRsb2coY2FzZV9pZCA9ICJwYXRpZW50IiwNCiAgICAgICAgICAgICBhY3Rpdml0eV9pZCA9ICJoYW5kbGluZyIsDQogICAgICAgICAgICAgYWN0aXZpdHlfaW5zdGFuY2VfaWQgPSAiaGFuZGxpbmdfaWQiLA0KICAgICAgICAgICAgIGxpZmVjeWNsZV9pZCA9ICJyZWdpc3RyYXRpb25fdHlwZSIsDQogICAgICAgICAgICAgdGltZXN0YW1wID0gInRpbWUiLA0KICAgICAgICAgICAgIHJlc291cmNlX2lkID0gImVtcGxveWVlIikgJT4lDQogICAgdG9fYWN0aXZpdHlsb2coKSAtPiBzYzJfYWN0aXZpdHlsb2cNCg0Kc2MyX2FjdGl2aXR5bG9nDQpgYGANCg0KIyAyLjQgRGF0YSB2aXN1YWxpemF0aW9uDQojIyAyLjQuMSBQcm9jZXNzbWFwLCBmcmVxdWVuY3kNCmBgYHtyfQ0KI2ZyZXF1ZW5jeTogYWJzb2x1dGUsIGFic29sdXRlX2Nhc2UsIHJlbGF0aXZlLCByZWxhdGl2ZV9jYXNlDQpwcmludChwcm9jZXNzX21hcChzYzJfYWN0aXZpdHlsb2csIHR5cGU9ZnJlcXVlbmN5KCJhYnNvbHV0ZSIpKSkNCmBgYA0KDQojIyAyLjQuMiBQcm9jZXNzbWFwLCBwZXJmb3JtYW5jZQ0KYGBge3J9DQojcGVyZm9ybWFuY2U6IG1lZGlhbi9tZWFuLCAieWVhcnMiLyJzZW1lc3RlcnMiLyJxdWFydGVycyIvIm1vbnRocyIvIndlZWtzIi8iZGF5cyIvImhvdXJzIi8ibWlucyIvInNlY3MiDQpwcmludChwcm9jZXNzX21hcChzYzJfYWN0aXZpdHlsb2csIHR5cGU9cGVyZm9ybWFuY2UobWVkaWFuLCJzZWNzIikpKQ0KYGBgDQoNCiMjIDIuNC4zIFJlc3NvdXJjZW1hcCwgZnJlcXVlbmN5DQpgYGB7cn0NCnJlc291cmNlX21hcChzYzJfYWN0aXZpdHlsb2csIHR5cGU9ZnJlcXVlbmN5KCJhYnNvbHV0ZSIpKQ0KYGBgDQoNCiMjIDIuNC40IFJlc3NvdXJjZW1hcCwgcGVyZm9ybWFuY2UNCmBgYHtyfQ0KcmVzb3VyY2VfbWFwKHNjMl9hY3Rpdml0eWxvZywgdHlwZT1wZXJmb3JtYW5jZShtZWRpYW4sInNlY3MiKSkNCmBgYA0KDQojIDMuIFNjZW5hcmlvIDMNCiMjIDMuMSBSZWFkIGRhdGENCmBgYHtyfQ0Kc2MzX2RhdGEgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL25pa29sL0Rvd25sb2Fkcy9zY2VuYXJpbzMuY3N2Iiwgc2VwPSI7IikNCmBgYA0KDQojIyAzLjIgQW5hbHl6ZSBkYXRhIHN0cnVjdHVyZQ0KYGBge3J9DQpoZWFkKHNjM19kYXRhKQ0KYGBgDQoNCiMjIDMuMyBEYXRhIHdyYW5nbGluZw0KYGBge3J9DQpzYzNfYWN0aXZpdHlsb2cgPC0gc2MzX2RhdGEgJT4lDQogICAgIyByZWNvZGUgbGlmZWN5Y2xlIHZhcmlhYmxlIGFwcHJvcHJpYXRlbHkNCiAgICBkcGx5cjo6bXV0YXRlKHJlZ2lzdHJhdGlvbl90eXBlID0gZm9yY2F0czo6ZmN0X3JlY29kZShyZWdpc3RyYXRpb25fdHlwZSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInN0YXJ0IiA9ICJzdGFydGVkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiY29tcGxldGUiID0gImNvbXBsZXRlZCIpKSAlPiUNCiAgICBjb252ZXJ0X3RpbWVzdGFtcHMoY29sdW1ucyA9ICJ0aW1lIiwgZm9ybWF0ID0geW1kX2htcykgJT4lDQogICAgZXZlbnRsb2coY2FzZV9pZCA9ICJwYXRpZW50IiwNCiAgICAgICAgICAgICAgICBhY3Rpdml0eV9pZCA9ICJoYW5kbGluZyIsDQogICAgICAgICAgICAgICAgYWN0aXZpdHlfaW5zdGFuY2VfaWQgPSAiaGFuZGxpbmdfaWQiLA0KICAgICAgICAgICAgICAgIGxpZmVjeWNsZV9pZCA9ICJyZWdpc3RyYXRpb25fdHlwZSIsDQogICAgICAgICAgICAgICAgdGltZXN0YW1wID0gInRpbWUiLA0KICAgICAgICAgICAgICAgIHJlc291cmNlX2lkID0gImVtcGxveWVlIikgDQpzYzNfYWN0aXZpdHlsb2cNCmBgYA0KDQojIDMuNCBEYXRhIHZpc3VhbGl6YXRpb24NCiMjIDMuNC4xIFByb2Nlc3NtYXAsIGZyZXF1ZW5jeQ0KYGBge3J9DQojZnJlcXVlbmN5OiBhYnNvbHV0ZSwgYWJzb2x1dGVfY2FzZSwgcmVsYXRpdmUsIHJlbGF0aXZlX2Nhc2UNCnByaW50KHByb2Nlc3NfbWFwKHNjM19hY3Rpdml0eWxvZywgdHlwZT1mcmVxdWVuY3koImFic29sdXRlIikpKQ0KYGBgDQoNCiMjIDMuNC4yIFByb2Nlc3NtYXAsIHBlcmZvcm1hbmNlDQpgYGB7cn0NCiNwZXJmb3JtYW5jZTogbWVkaWFuL21lYW4sICJ5ZWFycyIvInNlbWVzdGVycyIvInF1YXJ0ZXJzIi8ibW9udGhzIi8id2Vla3MiLyJkYXlzIi8iaG91cnMiLyJtaW5zIi8ic2VjcyINCnByaW50KHByb2Nlc3NfbWFwKHNjM19hY3Rpdml0eWxvZywgdHlwZT1wZXJmb3JtYW5jZShtZWRpYW4sInNlY3MiKSkpDQpgYGANCg0KIyMgMy40LjMgUmVzc291cmNlbWFwLCBmcmVxdWVuY3kNCmBgYHtyfQ0KcmVzb3VyY2VfbWFwKHNjM19hY3Rpdml0eWxvZywgdHlwZT1mcmVxdWVuY3koImFic29sdXRlIikpDQpgYGANCg0KIyMgMy40LjQgUmVzc291cmNlbWFwLCBwZXJmb3JtYW5jZQ0KYGBge3J9DQpyZXNvdXJjZV9tYXAoc2MzX2FjdGl2aXR5bG9nLCB0eXBlPXBlcmZvcm1hbmNlKG1lZGlhbiwic2VjcyIpKQ0KYGBgDQoNCiMgNC4gR2VuZXJhbCBwcmVzZW50YXRpb24gb2YgdGhlIGRpZmZlcmVudCBwb3NzaWJpbGl0aWVzIHJlZ2FyZGluZyBkYXRhIHZpc3VhbGl6YXRpb24gYW5kIGFuYWx5c2lzIA0KIyMgNC4xIEZyZXF1ZW5jeSBtYXBzDQpJbiB0aGUgZXhhbXBsZXMgYmVsb3csIHdlIHdpbGwgdXNlIGEgc2xpZ2h0bHkgZmlsdGVyZWQgdmVyc2lvbnMgb2YgdGhlIHRyYWZmaWNfZmluZXMgZGF0YSBzZXQsIHdoaWNoIGNvbnRhaW5zIDk1JSBvZiB0aGUgY2FzZXMgdGhhdCBoYXZlIHRoZSBtb3N0IGZyZXF1ZW50IHRyYWNlcy4NCmBgYHtyfQ0KdG1wIDwtIHRyYWZmaWNfZmluZXMgJT4lDQogICAgZmlsdGVyX3RyYWNlX2ZyZXF1ZW5jeShwZXJjZW50YWdlID0gMC45NSkNCmBgYA0KDQojIyMgQWJzb2x1dGUNCkluIHRoZSBleGFtcGxlcyBiZWxvdywgSSB3aWxsIHVzZSBhIHNsaWdodGx5IGZpbHRlcmVkIHZlcnNpb24gb2YgdGhlIHRyYWZmaWNfZmluZXMgZGF0YSBzZXQsIHdoaWNoIGNvbnRhaW5zIDk1JSBvZiB0aGUgY2FzZXMgd2l0aCB0aGUgbW9zdCBmcmVxdWVudCB0cmFjZXMuDQpgYGB7cn0NCnRtcCAlPiUNCiAgICBwcm9jZXNzX21hcChmcmVxdWVuY3koImFic29sdXRlIikpDQpgYGANCg0KIyMjIFJlbGF0aXZlDQpJbiByZWxhdGl2ZSB0ZXJtcywgSSBmb3VuZCB0aGF0IFBheW1lbnQgcmVwcmVzZW50cyAxNC41MSUgb2YgdGhlIHRvdGFsIGFjdGl2aXR5IGluc3RhbmNlcy4gQWRkaXRpb25hbGx5LCBJIG9ic2VydmVkIHRoYXQgaW4gOTQuNjYlIG9mIHRoZSBjYXNlcyB3aGVyZSBpdCBvY2N1cnJlZCwgaXQgbWFya2VkIHRoZSBlbmQgb2YgdGhlIGNhc2UuIEluIHRoZSByZW1haW5pbmcgNS4zNCUgb2YgY2FzZXMsIGl0IHdhcyBmb2xsb3dlZCBieSBhbm90aGVyIFBheW1lbnQuDQpgYGB7cn0NCnRtcCAlPiUNCiAgICBwcm9jZXNzX21hcChmcmVxdWVuY3koInJlbGF0aXZlIikpDQpgYGANCg0KIyMjIFJlbGF0aXZlIGNhc2UNCkJlbG93LCBJIGZvdW5kIHRoYXQgUGF5bWVudCBvY2N1cnJlZCBpbiA0Ni4yMSUgb2YgdGhlIGNhc2VzLiBJbiAyLjYlIG9mIHRoZSBjYXNlcywgSSBvYnNlcnZlZCB0aGF0IGEgUGF5bWVudCBhY3Rpdml0eSB3YXMgZm9sbG93ZWQgYnkgYW5vdGhlciBQYXltZW50Lg0KYGBge3J9DQp0bXAgJT4lDQogICAgcHJvY2Vzc19tYXAoZnJlcXVlbmN5KCJyZWxhdGl2ZS1jYXNlIikpDQpgYGANCg0KIyMjIFJlbGF0aXZlIGNvbnNlcXVlbnQNCkZpbmFsbHksIHRoZSByZWxhdGl2ZS1jb25zZXF1ZW50IG1hcCBzaG93cyB3aGF0IGhhcHBlbnMgYmVmb3JlIGFjdGl2aXRpZXMuIFdpdGggcmVzcGVjdCB0byBQYXltZW50LCBvbmUgY2FuIHNlZSB0aGF0IGl0IHdhcyBwcmVjZWRlZCBieToNCg0KICAgIENyZWF0ZSBGaW5lICg3My4xNSUpDQogICAgQWRkIFBlbmFsdHkgKDIxLjUxJSkNCiAgICBQYXltZW50ICg1LjM0JSkNCg0KUGF5bWVudCBpdHNlbGYgcmVwcmVzZW50cyAxNC41MSUgb2YgYWxsIGFjdGl2aXR5IGV4ZWN1dGlvbnMuDQpgYGB7cn0NCnRtcCAlPiUNCiAgICBwcm9jZXNzX21hcChmcmVxdWVuY3koInJlbGF0aXZlLWNvbnNlcXVlbnQiKSkNCmBgYA0KDQojIyA0LjIgUGVyZm9ybWFuY2UgcHJvZmlsZQ0KSW5zdGVhZCBvZiB1c2luZyBmcmVxdWVuY2llcywgSSBjYW4gYWxzbyB1c2UgcHJvY2VzcyBtYXBzIHRvIHZpc3VhbGl6ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIHByb2Nlc3MsIGJ5IHVzaW5nIHBlcmZvcm1hbmNlKCkgdG8gY29uZmlndXJlIHRoZSBtYXAgaW5zdGVhZCBvZiBmcmVxdWVuY3koKS4NCg0KVGhlcmUgYXJlIHRocmVlIGRpZmZlcmVudCBwYXJhbWV0ZXJzIHNwZWNpZmljIHRvIHRoZSBwZXJmb3JtYW5jZSgpIGNvbmZpZ3VyYXRpb24gdGhhdCBJIGNhbiBhZGp1c3Q6IHRoZSBhZ2dyZWdhdGlvbiBmdW5jdGlvbiwgdGhlIHRpbWUgdW5pdHMsIGFuZCB0aGUgZmxvdyB0aW1lIHR5cGUuDQpgYGB7cn0NCnBhdGllbnRzICU+JQ0KICAgIHByb2Nlc3NfbWFwKHBlcmZvcm1hbmNlKCkpDQpgYGANCg0KIyMjIEFnZ3JlZ2F0aW9uIGZ1bmN0aW9uDQpUaGUgRlVOIGFyZ3VtZW50IHNwZWNpZmllcyB0aGUgYWdncmVnYXRpb24gZnVuY3Rpb24gSSB3YW50IHRvIGFwcGx5IG9uIHRoZSBwcm9jZXNzaW5nIHRpbWUgKGUuZy4sIG1pbiwgbWF4LCBtZWFuLCBtZWRpYW4sIGV0Yy4pLiBCeSBkZWZhdWx0LCB0aGUgbWVhbiBkdXJhdGlvbnMgYXJlIHNob3duLCBidXQgSSBjYW4gYWRqdXN0IHRoaXMgdG8gdGhlIG1heGltdW0sIGZvciBleGFtcGxlLg0KYGBge3J9DQpwYXRpZW50cyAlPiUNCiAgICBwcm9jZXNzX21hcChwZXJmb3JtYW5jZShGVU4gPSBtYXgpKQ0KYGBgDQoNCkFueSBmdW5jdGlvbiB0aGF0IHRha2VzIGEgbnVtZXJpY2FsIHZlY3RvciBhbmQgcmV0dXJucyBhIHNpbmdsZSB2YWx1ZSBjYW4gYmUgdXNlZC4gRm9yIGV4YW1wbGUsIGlmIEkgd2FudCB0byBzaG93IHRoZSAwLjkwIHBlcmNlbnRpbGUsIEkgY2FuIHVzZSB0aGF0IGZ1bmN0aW9uLg0KYGBge3J9DQpwOTAgPC0gZnVuY3Rpb24oeCwgLi4uKSB7DQogICAgcXVhbnRpbGUoeCwgcHJvYnMgPSAwLjksIC4uLikNCn0NCg0KcGF0aWVudHMgJT4lDQogICAgcHJvY2Vzc19tYXAocGVyZm9ybWFuY2UoRlVOID0gcDkwKSkNCmBgYA0KDQojIyMgVGltZSB1bml0cw0KVGhlIHVuaXRzIGFyZ3VtZW50IGFsbG93cyBtZSB0byBzcGVjaWZ5IHRoZSB0aW1lIHVuaXRzIEkgd2FudCB0byB1c2UuDQoNCkZvciBleGFtcGxlIGluIGRheXM6DQpgYGB7cn0NCnBhdGllbnRzICU+JQ0KICAgIHByb2Nlc3NfbWFwKHBlcmZvcm1hbmNlKG1lYW4sICJkYXlzIikpDQpgYGANCg0KRm9yIGV4YW1wbGUgaW4gaG91cnM6DQpgYGB7cn0NCnBhdGllbnRzICU+JQ0KICAgIHByb2Nlc3NfbWFwKHBlcmZvcm1hbmNlKG1lYW4sICJob3VycyIpKQ0KYGBgDQoNCiMjIDQuMyBBZHZhbmNlZCBtYXBzDQojIyMgQ29tYmluaW5nIGRpZmZlcmVudCBwcm9maWxlcw0KSSBjYW4gZGlmZmVyZW50aWF0ZSB0aGUgcHJvZmlsZSB1c2VkIGZvciBub2RlcyBhbmQgZWRnZXMgYnkgdXNpbmcgdGhlIHR5cGVfbm9kZXMgYW5kIHR5cGVfZWRnZXMgYXR0cmlidXRlcyBpbnN0ZWFkIG9mIHRoZSB0eXBlIGFyZ3VtZW50LiBUaGlzIHdheSwgSSBjYW4gY29tYmluZSBpbmZvcm1hdGlvbiBhYm91dCBmcmVxdWVuY2llcywgcGVyZm9ybWFuY2UsIG9yIGFueSBvdGhlciB2YWx1ZSBpbiB0aGUgc2FtZSBncmFwaC4NCmBgYHtyfQ0KcGF0aWVudHMgJT4lDQogICAgcHJvY2Vzc19tYXAodHlwZV9ub2RlcyA9IGZyZXF1ZW5jeSgicmVsYXRpdmVfY2FzZSIpLA0KICAgICAgICAgICAgICAgIHR5cGVfZWRnZXMgPSBwZXJmb3JtYW5jZShtZWFuKSkNCmBgYA0KDQojIyMgQWRkaW5nIHNlY29uZGFyeSBpbmZvcm1hdGlvbg0KSSBjYW4gYWRkIGEgc2Vjb25kIGxheWVyIG9mIGluZm9ybWF0aW9uIHRvIGJvdGggbm9kZXMgYW5kIGVkZ2VzLg0KYGBge3J9DQpwYXRpZW50cyAlPiUNCiAgICBwcm9jZXNzX21hcCh0eXBlID0gZnJlcXVlbmN5KCJyZWxhdGl2ZV9jYXNlIiksDQogICAgICAgICAgICAgICAgc2VjID0gZnJlcXVlbmN5KCJhYnNvbHV0ZSIpKQ0KYGBgDQoNCkkgY2FuIGRpZmZlcmVudGlhdGUgYm90aCBwcmltYXJ5IGFuZCBzZWNvbmRhcnkgbGF5ZXJzIGJldHdlZW4gbm9kZXMgYW5kIGVkZ2VzLg0KYGBge3J9DQpwYXRpZW50cyAlPiUNCiAgICBwcm9jZXNzX21hcCh0eXBlX25vZGVzID0gIGZyZXF1ZW5jeSgicmVsYXRpdmVfY2FzZSIpLA0KICAgICAgICAgICAgICAgIHR5cGVfZWRnZXMgPSBwZXJmb3JtYW5jZSh1bml0cyA9ICJob3VycyIpLA0KICAgICAgICAgICAgICAgIHNlY19ub2RlcyA9IGZyZXF1ZW5jeSgiYWJzb2x1dGUiKSwNCiAgICAgICAgICAgICAgICBzZWNfZWRnZXMgPSBwZXJmb3JtYW5jZShGVU4gPSBtYXgsIHVuaXRzID0gImhvdXJzIikpDQpgYGANCg0KIyMjIEN1c3RvbWl6aW5nIGNvbG9ycw0KQm90aCBmcmVxdWVuY3koKSBhbmQgcGVyZm9ybWFuY2UoKSBoYXZlIHRoZSBhcmd1bWVudHMgY29sb3JcX3NjYWxlIGFuZCBjb2xvclxfZWRnZXMgdG8gY3VzdG9taXplIHRoZSBjb2xvcnMgaW4gdGhlIHByb2Nlc3MgbWFwOg0KDQoqICoqY29sb3Jfc2NhbGUqKjogSSBjYW4gc2V0IHRoZSBjb2xvciBzY2FsZSB0byBmaWxsIHRoZSBub2Rlcy4gSXQgY2FuIGJlIGFueSBvZiB0aGUgc2NhbGVzIGluIFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbC5pbmZvLiBCeSBkZWZhdWx0LCBpdOKAmXMgc2V0IHRvIFB1QnUgKGZvciBmcmVxdWVuY3kpIG9yIFJlZHMgKGZvciBwZXJmb3JtYW5jZSkuDQoqICoqY29sb3JfZWRnZXMqKjogSSBjYW4gYXBwbHkgYW55IHNpbmdsZSBjb2xvciB0byB0aGUgYXJyb3dzLCBzdWNoIGFzIGEgbmFtZWQgY29sb3IsIGhleC1jb2RlLCBvciBhIHJlc3VsdCBvZiByZ2IuIEJ5IGRlZmF1bHQsIGl04oCZcyBzZXQgdG8gZG9kZ2VyYmx1ZTQgKGZvciBmcmVxdWVuY3kpIG9yIHJlZDQgKGZvciBwZXJmb3JtYW5jZSkuDQoNCkNvbmZpZ3VyaW5nIHRoZSBjb2xvcnMgY2FuIGJlIHVzZWZ1bCBmb3IgaGFybW9uaXppbmcgdGhlIHByb2Nlc3MgbWFwIGFlc3RoZXRpY3Mgd2hlbiB1c2luZyBkaWZmZXJlbnQgbGF5ZXJzIGZvciBub2RlcyBhbmQgZWRnZXMuDQoNCg0KYGBge3J9DQpwYXRpZW50cyAlPiUNCiAgICBwcm9jZXNzX21hcCh0eXBlX25vZGVzID0gZnJlcXVlbmN5KCJyZWxhdGl2ZV9jYXNlIiwgY29sb3Jfc2NhbGUgPSAiUHVCdSIpLA0KICAgICAgICAgICAgICAgIHR5cGVfZWRnZXMgPSBwZXJmb3JtYW5jZShtZWFuLCBjb2xvcl9lZGdlcyA9ICJkb2RnZXJibHVlNCIpKQ0KYGBgDQoNCiMjIDQuNCBBbmltYXRlIE1hcHMNCkhlcmUsIEkgdXNlIHRoZSBwYXRpZW50cycgZXZlbnQgbG9nIHByb3ZpZGVkIGJ5IHRoZSBldmVudGRhdGFSIHBhY2thZ2UuDQoNCkhlcmUncyBhIGJhc2ljIGFuaW1hdGlvbiB3aXRoIHN0YXRpYyBjb2xvciBhbmQgdG9rZW4gc2l6ZToNCmBgYHtyfQ0KYW5pbWF0ZV9wcm9jZXNzKHBhdGllbnRzKQ0KYGBgDQoNCkkgY2FuIGNoYW5nZSB0aGUgZGVmYXVsdCB0b2tlbiBjb2xvciwgc2l6ZSwgb3IgaW1hZ2UgYXMgZm9sbG93czoNCmBgYHtyfQ0KYW5pbWF0ZV9wcm9jZXNzKHBhdGllbnRzLCBtYXBwaW5nID0gdG9rZW5fYWVzKHNpemUgPSB0b2tlbl9zY2FsZSgxMiksIHNoYXBlID0gInJlY3QiKSkNCmBgYA0KDQpEaWZmZXJlbnQgdG9rZW4gY29sb3IuDQpgYGB7cn0NCmFuaW1hdGVfcHJvY2VzcyhwYXRpZW50cywgbWFwcGluZyA9IHRva2VuX2Flcyhjb2xvciA9IHRva2VuX3NjYWxlKCJyZWQiKSkpDQpgYGANCg0KU29tZSBjb21iaW5hdGlvbnMgb2Ygb3B0aW9ucyBhcyBtZW50aW9uZWQgYWJvdmUuDQpgYGB7cn0NCmFuaW1hdGVfcHJvY2VzcyhwYXRpZW50cywgbW9kZSA9ICJyZWxhdGl2ZSIsIGppdHRlciA9IDEwLCBsZWdlbmQgPSAiY29sb3IiLA0KICBtYXBwaW5nID0gdG9rZW5fYWVzKGNvbG9yID0gdG9rZW5fc2NhbGUoImVtcGxveWVlIiwgDQogICAgc2NhbGUgPSAib3JkaW5hbCIsIA0KICAgIHJhbmdlID0gUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDcsICJQYWlyZWQiKSkpKQ0KYGBgDQoNCiMjIDQuNSBQcm9jZXNzIE1hdHJpeA0KIyMjIEFic29sdXRlDQpgYGB7cn0NCnRyYWZmaWNfZmluZXMgJT4lDQogICAgcHJvY2Vzc19tYXRyaXgoZnJlcXVlbmN5KCJhYnNvbHV0ZSIpKSANCmBgYA0KDQpUaGUgQWJzb2x1dGUgUHJvY2VzcyBNYXRyaXggaXMgYSB0b29sIEkgdXNlIHRvIHZpc3VhbGl6ZSB0aGUgZnJlcXVlbmN5IG9mIHRyYW5zaXRpb25zIGJldHdlZW4gYWN0aXZpdGllcyBpbiBhIHByb2Nlc3MsIHdoZXJlIHRoZSBtYXRyaXggZGlzcGxheXMgdGhlIGNvdW50IG9mIG9jY3VycmVuY2VzIGZvciBlYWNoIHBhaXIgb2YgYWN0aXZpdGllcy4NCmBgYHtyfQ0KdHJhZmZpY19maW5lcyAlPiUNCiAgICBwcm9jZXNzX21hdHJpeChmcmVxdWVuY3koImFic29sdXRlIikpICU+JQ0KICAgIHBsb3QoKQ0KYGBgDQoNCiMjIyBSZWxhdGl2ZS1jYXNlDQpgYGB7cn0NCnRyYWZmaWNfZmluZXMgJT4lDQogICAgcHJvY2Vzc19tYXRyaXgoZnJlcXVlbmN5KCJyZWxhdGl2ZS1jYXNlIikpIA0KYGBgDQoNClRoZSBSZWxhdGl2ZS1jYXNlIFByb2Nlc3MgTWF0cml4IGlzIGEgdG9vbCBJIHVzZSB0byB2aXN1YWxpemUgdGhlIHRyYW5zaXRpb25zIGJldHdlZW4gYWN0aXZpdGllcyBpbiBhIHByb2Nlc3MsIHdoZXJlIHRoZSBtYXRyaXggc2hvd3MgdGhlIGZyZXF1ZW5jeSBvZiBlYWNoIHRyYW5zaXRpb24gcmVsYXRpdmUgdG8gdGhlIHRvdGFsIG51bWJlciBvZiBjYXNlcywgcHJvdmlkaW5nIGluc2lnaHRzIGludG8gdGhlIHByb3BvcnRpb24gb2YgY2FzZXMgdGhhdCBmb2xsb3cgc3BlY2lmaWMgYWN0aXZpdHkgcGF0aHMuDQpgYGB7cn0NCnRyYWZmaWNfZmluZXMgJT4lDQogICAgcHJvY2Vzc19tYXRyaXgoZnJlcXVlbmN5KCJyZWxhdGl2ZS1jYXNlIikpICU+JQ0KICAgIHBsb3QoKQ0KYGBgDQoNCiMjIyBSZWxhdGl2ZS1hbnRlY2VkZW50DQpgYGB7cn0NCnRyYWZmaWNfZmluZXMgJT4lDQogICAgcHJvY2Vzc19tYXRyaXgoZnJlcXVlbmN5KCJyZWxhdGl2ZS1hbnRlY2VkZW50IikpIA0KYGBgDQoNClRoZSBSZWxhdGl2ZS1hbnRlY2VkZW50IFByb2Nlc3MgTWF0cml4IGlzIGEgdG9vbCBJIHVzZSB0byB2aXN1YWxpemUgdGhlIGZyZXF1ZW5jeSBvZiB0cmFuc2l0aW9ucyBiZXR3ZWVuIGFjdGl2aXRpZXMgaW4gYSBwcm9jZXNzLCB3aGVyZSBpdCBzaG93cyBob3cgb2Z0ZW4gZWFjaCBhY3Rpdml0eSBpcyBwcmVjZWRlZCBieSBzcGVjaWZpYyBhbnRlY2VkZW50IGFjdGl2aXRpZXMsIGV4cHJlc3NlZCByZWxhdGl2ZSB0byB0aGUgdG90YWwgbnVtYmVyIG9mIGNhc2VzLg0KYGBge3J9DQp0cmFmZmljX2ZpbmVzICU+JQ0KICAgIHByb2Nlc3NfbWF0cml4KGZyZXF1ZW5jeSgicmVsYXRpdmUtYW50ZWNlZGVudCIpKSAlPiUNCiAgICBwbG90KCkNCmBgYA0KDQojIyMgUmVsYXRpdmUtY29uc2VxdWVudA0KYGBge3J9DQp0cmFmZmljX2ZpbmVzICU+JQ0KICAgIHByb2Nlc3NfbWF0cml4KGZyZXF1ZW5jeSgicmVsYXRpdmUtY29uc2VxdWVudCIpKSANCmBgYA0KDQpUaGUgUmVsYXRpdmUtY29uc2VxdWVudCBQcm9jZXNzIE1hdHJpeCBpcyBhIHRvb2wgSSB1c2UgdG8gdmlzdWFsaXplIHRoZSBmcmVxdWVuY3kgb2YgdHJhbnNpdGlvbnMgYmV0d2VlbiBhY3Rpdml0aWVzIGluIGEgcHJvY2Vzcywgd2hlcmUgaXQgc2hvd3MgaG93IG9mdGVuIGVhY2ggYWN0aXZpdHkgaXMgZm9sbG93ZWQgYnkgc3BlY2lmaWMgc3Vic2VxdWVudCBhY3Rpdml0aWVzLCBleHByZXNzZWQgcmVsYXRpdmUgdG8gdGhlIHRvdGFsIG51bWJlciBvZiBjYXNlcy4NCmBgYHtyfQ0KdHJhZmZpY19maW5lcyAlPiUNCiAgICBwcm9jZXNzX21hdHJpeChmcmVxdWVuY3koInJlbGF0aXZlLWNvbnNlcXVlbnQiKSkgJT4lDQogICAgcGxvdCgpDQpgYGANCg0KIyMjIFBlcmZvcm1hbmNlDQpgYGB7cn0NCnRyYWZmaWNfZmluZXMgJT4lDQogICAgcHJvY2Vzc19tYXRyaXgocGVyZm9ybWFuY2UoRlVOID0gbWVhbiwgdW5pdHMgPSAid2Vla3MiKSkgDQpgYGANCg0KVGhlIFBlcmZvcm1hbmNlIFByb2Nlc3MgTWF0cml4IGlzIGEgdG9vbCBJIHVzZSB0byB2aXN1YWxpemUgbm90IG9ubHkgdGhlIGZyZXF1ZW5jeSBvZiBhY3Rpdml0eSB0cmFuc2l0aW9ucyBidXQgYWxzbyB0aGUgcGVyZm9ybWFuY2UgbWV0cmljcywgc3VjaCBhcyB0aGUgdGltZSB0YWtlbiBmb3IgZWFjaCB0cmFuc2l0aW9uLCBhbGxvd2luZyBtZSB0byBhbmFseXplIGhvdyBlZmZpY2llbnRseSBkaWZmZXJlbnQgcHJvY2VzcyBwYXRocyBhcmUgcGVyZm9ybWVkLg0KYGBge3J9DQp0cmFmZmljX2ZpbmVzICU+JQ0KICAgIHByb2Nlc3NfbWF0cml4KHBlcmZvcm1hbmNlKEZVTiA9IG1lYW4sIHVuaXRzID0gIndlZWtzIikpICAlPiUNCiAgICBwbG90KCkNCmBgYA0KDQojIyMgU3VtbWFyeQ0KVGhlIHZhcmlvdXMgdmVyc2lvbnMgb2YgdGhlIHByb2Nlc3MgbWF0cmljZXMgcHJvdmlkZSBkaWZmZXJlbnQgcGVyc3BlY3RpdmVzIG9uIHRoZSB0cmFuc2l0aW9ucyBiZXR3ZWVuIGFjdGl2aXRpZXMgaW4gYSBwcm9jZXNzLg0KDQoqICoqQWJzb2x1dGUgUHJvY2VzcyBNYXRyaXgqKiBkaXNwbGF5cyB0aGUgcmF3IGZyZXF1ZW5jeSBvZiB0cmFuc2l0aW9ucyBiZXR3ZWVuIGFjdGl2aXRpZXMsIHNob3dpbmcgdGhlIHRvdGFsIGNvdW50IG9mIG9jY3VycmVuY2VzIGZvciBlYWNoIHBhaXIgb2YgYWN0aXZpdGllcywgcmVnYXJkbGVzcyBvZiB0aGUgbnVtYmVyIG9mIGNhc2VzLg0KDQoqICoqUmVsYXRpdmUtY2FzZSBQcm9jZXNzIE1hdHJpeCoqIHByb3ZpZGVzIGEgbm9ybWFsaXplZCB2aWV3IGJ5IHNob3dpbmcgdGhlIGZyZXF1ZW5jeSBvZiB0cmFuc2l0aW9ucyBhcyBhIHByb3BvcnRpb24gb2YgdGhlIHRvdGFsIG51bWJlciBvZiBjYXNlcy4gVGhpcyBhbGxvd3MgZm9yIGJldHRlciBpbnNpZ2h0IGludG8gdGhlIHJlbGF0aXZlIG9jY3VycmVuY2Ugb2YgZWFjaCBhY3Rpdml0eSBwYWlyIGluIHRoZSBvdmVyYWxsIHByb2Nlc3MuDQoNCiogKipSZWxhdGl2ZS1hbnRlY2VkZW50IFByb2Nlc3MgTWF0cml4KiogZm9jdXNlcyBvbiB0aGUgYWN0aXZpdGllcyB0aGF0IHByZWNlZGUgb3RoZXJzLiBJdCBzaG93cyB0aGUgZnJlcXVlbmN5IG9mIHRyYW5zaXRpb25zIHdoZXJlIGVhY2ggYWN0aXZpdHkgaXMgcHJlY2VkZWQgYnkgc3BlY2lmaWMgYW50ZWNlZGVudCBhY3Rpdml0aWVzLCBub3JtYWxpemVkIGJ5IHRoZSB0b3RhbCBudW1iZXIgb2YgY2FzZXMuDQoNCiogKipSZWxhdGl2ZS1jb25zZXF1ZW50IFByb2Nlc3MgTWF0cml4KiogbG9va3MgYXQgdGhlIGFjdGl2aXRpZXMgdGhhdCBmb2xsb3cgb3RoZXJzLiBJdCBzaG93cyB0aGUgZnJlcXVlbmN5IG9mIHRyYW5zaXRpb25zIHdoZXJlIGVhY2ggYWN0aXZpdHkgaXMgZm9sbG93ZWQgYnkgc3BlY2lmaWMgY29uc2VxdWVudCBhY3Rpdml0aWVzLCBhZ2FpbiBleHByZXNzZWQgcmVsYXRpdmUgdG8gdGhlIHRvdGFsIG51bWJlciBvZiBjYXNlcy4NCg0KKiAqKlBlcmZvcm1hbmNlIFByb2Nlc3MgTWF0cml4KiogY29tYmluZXMgZnJlcXVlbmN5IGFuYWx5c2lzIHdpdGggcGVyZm9ybWFuY2UgbWV0cmljcywgZGlzcGxheWluZyBob3cgbG9uZyBlYWNoIHRyYW5zaXRpb24gdGFrZXMgYW5kIGhpZ2hsaWdodGluZyB0aGUgZWZmaWNpZW5jeSBvZiBkaWZmZXJlbnQgcGF0aHMgaW4gdGhlIHByb2Nlc3MuDQoNCkluIHN1bW1hcnksIHdoaWxlIHRoZSBBYnNvbHV0ZSBQcm9jZXNzIE1hdHJpeCBnaXZlcyByYXcgY291bnRzLCB0aGUgcmVsYXRpdmUgbWF0cmljZXMgcHJvdmlkZSBub3JtYWxpemVkIGluc2lnaHRzIGludG8gdGhlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBhY3Rpdml0aWVzLCBhbmQgdGhlIFBlcmZvcm1hbmNlIFByb2Nlc3MgTWF0cml4IGFkZHMgYSBsYXllciBvZiBhbmFseXNpcyBvbiB0aGUgdGltZSBvciBlZmZpY2llbmN5IG9mIHRyYW5zaXRpb25zLg0KDQojIyA0LjYgRG90dGVkIENoYXJ0DQojIyMgQWJzb2x1dGUNClRoZSBBYnNvbHV0ZSBEb3R0ZWQgQ2hhcnQgaXMgYSB2aXN1YWxpemF0aW9uIHRvb2wgSSB1c2UgdG8gZGlzcGxheSB0aGUgZnJlcXVlbmN5IG9mIGFjdGl2aXR5IG9jY3VycmVuY2VzIGluIGEgcHJvY2Vzcywgd2hlcmUgZWFjaCBhY3Rpdml0eSBpcyByZXByZXNlbnRlZCBieSBhIGRvdCwgYW5kIHRoZSB0b3RhbCBjb3VudCBvZiBlYWNoIGFjdGl2aXR5IGlzIHNob3duIGFzIHRoZSBudW1iZXIgb2YgZG90cywgcHJvdmlkaW5nIGEgY2xlYXIgdmlldyBvZiBhY3Rpdml0eSBkaXN0cmlidXRpb24uDQpgYGB7cn0NCnNlcHNpcyAlPiUNCiAgICBkb3R0ZWRfY2hhcnQoeCA9ICJhYnNvbHV0ZSIpDQpgYGANCg0KVGhlIEFic29sdXRlIERvdHRlZCBDaGFydCB3aXRoIHRoZSBzb3J0ID0gImVuZCIgb3B0aW9uIGFycmFuZ2VzIHRoZSBhY3Rpdml0aWVzIGluIHRoZSBwcm9jZXNzIGJhc2VkIG9uIHRoZWlyIG9jY3VycmVuY2UgYXQgdGhlIGVuZCBvZiB0aGUgY2FzZXMsIGFsbG93aW5nIG1lIHRvIGZvY3VzIG9uIHRoZSBmaW5hbCBhY3Rpdml0aWVzIGFuZCB0aGVpciBmcmVxdWVuY2llcyBpbiB0aGUgcHJvY2VzcyBmbG93Lg0KYGBge3J9DQpzZXBzaXMgJT4lDQogICAgZG90dGVkX2NoYXJ0KHggPSAiYWJzb2x1dGUiLCBzb3J0ID0gImVuZCIpDQpgYGANCg0KIyMjIFJlbGF0aXZlDQpUaGUgUmVsYXRpdmUgRG90dGVkIENoYXJ0IHZpc3VhbGl6ZXMgdGhlIHJlbGF0aXZlIGZyZXF1ZW5jeSBvZiBhY3Rpdml0eSBvY2N1cnJlbmNlcyBpbiBhIHByb2Nlc3MsIG5vcm1hbGl6aW5nIHRoZSBkYXRhIHRvIHNob3cgZWFjaCBhY3Rpdml0eSdzIHByb3BvcnRpb24gaW4gcmVsYXRpb24gdG8gdGhlIHRvdGFsIG51bWJlciBvZiBjYXNlcy4gRWFjaCBkb3QgcmVwcmVzZW50cyBhbiBhY3Rpdml0eSwgYW5kIHRoZSBudW1iZXIgb2YgZG90cyByZWZsZWN0cyBpdHMgcmVsYXRpdmUgZnJlcXVlbmN5LCBoZWxwaW5nIHRvIGNvbXBhcmUgdGhlIHByZXZhbGVuY2Ugb2YgZGlmZmVyZW50IGFjdGl2aXRpZXMgaW4gdGhlIHByb2Nlc3MuDQpgYGB7cn0NCnNlcHNpcyAlPiUNCiAgICBkb3R0ZWRfY2hhcnQoeCA9ICJyZWxhdGl2ZSIpDQpgYGANCiMjIyBSZWxhdGl2ZSB3ZWVrIDENClRoZSByZWxhdGl2ZV93ZWVrIERvdHRlZCBDaGFydCBkaXNwbGF5cyB0aGUgcmVsYXRpdmUgZnJlcXVlbmN5IG9mIGFjdGl2aXR5IG9jY3VycmVuY2VzIHdlZWsgYnkgd2VlaywgYWxsb3dpbmcgbWUgdG8gYW5hbHl6ZSBob3cgdGhlIHByZXZhbGVuY2Ugb2YgYWN0aXZpdGllcyBjaGFuZ2VzIG92ZXIgdGltZSBvbiBhIHdlZWtseSBiYXNpcyB3aXRoIGdncGxvdDIgY29sb3JzLg0KYGBge3J9DQpzZXBzaXMgJT4lDQogICAgZG90dGVkX2NoYXJ0KHggPSAicmVsYXRpdmVfd2VlayIsDQogICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yID0gZ2dwbG90Mjo6c2NhbGVfY29sb3JfZGlzY3JldGUpDQpgYGANCg0KIyMjIFJlbGF0aXZlIGRheQ0KVGhlIHJlbGF0aXZlX2RheSBEb3R0ZWQgQ2hhcnQgc2hvd3MgdGhlIHJlbGF0aXZlIGZyZXF1ZW5jeSBvZiBhY3Rpdml0eSBvY2N1cnJlbmNlcyBvbiBhIGRhaWx5IGJhc2lzLCBoZWxwaW5nIG1lIGFuYWx5emUgaG93IHRoZSBkaXN0cmlidXRpb24gb2YgYWN0aXZpdGllcyB2YXJpZXMgZnJvbSBkYXkgdG8gZGF5Lg0KYGBge3J9DQpzZXBzaXMgJT4lDQogICAgZG90dGVkX2NoYXJ0KHggPSAicmVsYXRpdmVfZGF5IikNCmBgYA0KDQojIyMgUmVsYXRpdmUgd2VlayAyDQpUaGUgcmVsYXRpdmVfd2VlayBEb3R0ZWQgQ2hhcnQgZGlzcGxheXMgdGhlIHJlbGF0aXZlIGZyZXF1ZW5jeSBvZiBhY3Rpdml0eSBvY2N1cnJlbmNlcyB3ZWVrIGJ5IHdlZWssIGFsbG93aW5nIG1lIHRvIGFuYWx5emUgaG93IHRoZSBwcmV2YWxlbmNlIG9mIGFjdGl2aXRpZXMgY2hhbmdlcyBvdmVyIHRpbWUgb24gYSB3ZWVrbHkgYmFzaXMuDQpgYGB7cn0NCnNlcHNpcyAlPiUNCiAgICBkb3R0ZWRfY2hhcnQoeCA9ICJyZWxhdGl2ZV93ZWVrIikNCmBgYA0KDQojIyA0LjcgVHJhY2UgZXhwbG9yZXINClRoZSB0cmFjZV9leHBsb3JlcigpIGZ1bmN0aW9uIGFsbG93cyBtZSB0byBleHBsb3JlIGluZGl2aWR1YWwgY2FzZSB0cmFjZXMgd2l0aGluIGEgcHJvY2VzcywgcHJvdmlkaW5nIGluc2lnaHRzIGludG8gdGhlIHNlcXVlbmNlIG9mIGFjdGl2aXRpZXMgYW5kIGhlbHBpbmcgdG8gaWRlbnRpZnkgcGF0dGVybnMgb3IgYW5vbWFsaWVzIGluIHNwZWNpZmljIGNhc2UgZXhlY3V0aW9ucy4NCmBgYHtyfQ0Kc2Vwc2lzICU+JQ0KICAgIHRyYWNlX2V4cGxvcmVyKCkNCmBgYA0KDQpUaGUgY29kZSBgc2Vwc2lzICU+JSB0cmFjZV9leHBsb3Jlcihjb3ZlcmFnZSA9IDAuMTUpYCBhbGxvd3MgbWUgdG8gZXhwbG9yZSB0aGUgdHJhY2VzIGluIHRoZSBzZXBzaXMgZGF0YXNldCwgZm9jdXNpbmcgb24gY2FzZXMgd2hlcmUgYXQgbGVhc3QgMTUlIG9mIHRoZSBhY3Rpdml0aWVzIGFyZSBjb3ZlcmVkLCBoZWxwaW5nIHRvIGFuYWx5emUgbW9yZSByZXByZXNlbnRhdGl2ZSBwcm9jZXNzIHBhdGhzLg0KYGBge3J9DQpzZXBzaXMgJT4lDQogICAgdHJhY2VfZXhwbG9yZXIoY292ZXJhZ2UgPSAwLjE1KQ0KYGBgDQoNClRoZSBjb2RlIGBzZXBzaXMgJT4lIHRyYWNlX2V4cGxvcmVyKG5fdHJhY2VzID0gMTApYCBlbmFibGVzIG1lIHRvIGV4cGxvcmUgdGhlIGZpcnN0IDEwIHRyYWNlcyBpbiB0aGUgc2Vwc2lzIGRhdGFzZXQsIHByb3ZpZGluZyBhIGNsb3NlciBsb29rIGF0IGEgc3Vic2V0IG9mIHRoZSBwcm9jZXNzIGZsb3dzIGZvciBkZXRhaWxlZCBhbmFseXNpcy4NCmBgYHtyfQ0Kc2Vwc2lzICU+JQ0KICAgIHRyYWNlX2V4cGxvcmVyKG5fdHJhY2VzID0gMTApDQpgYGANCg0KVGhlIGNvZGUgYHNlcHNpcyAlPiUgdHJhY2VfZXhwbG9yZXIobl90cmFjZXMgPSAxMCwgdHlwZSA9ICJpbmZyZXF1ZW50IilgIGFsbG93cyBtZSB0byBleHBsb3JlIHRoZSAxMCBsZWFzdCBmcmVxdWVudCB0cmFjZXMgaW4gdGhlIHNlcHNpcyBkYXRhc2V0LCBoZWxwaW5nIHRvIGFuYWx5emUgcmFyZSBvciB1bnVzdWFsIHByb2Nlc3MgcGF0aHMuDQpgYGB7cn0NCnNlcHNpcyAlPiUNCiAgICB0cmFjZV9leHBsb3JlcihuX3RyYWNlcyA9IDEwLCB0eXBlID0gImluZnJlcXVlbnQiKQ0KYGBgDQoNClRoZSBjb2RlIGBzZXBzaXMgJT4lIHRyYWNlX2V4cGxvcmVyKG5fdHJhY2VzID0gMTAsIGNvdmVyYWdlX2xhYmVscyA9IGMoImN1bXVsYXRpdmUiLCAicmVsYXRpdmUiKSlgIGVuYWJsZXMgbWUgdG8gZXhwbG9yZSB0aGUgZmlyc3QgMTAgdHJhY2VzIGluIHRoZSBzZXBzaXMgZGF0YXNldCwgZGlzcGxheWluZyBib3RoIGN1bXVsYXRpdmUgYW5kIHJlbGF0aXZlIGNvdmVyYWdlIGxhYmVscyB0byBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgZGlzdHJpYnV0aW9uIG9mIGFjdGl2aXR5IG9jY3VycmVuY2VzLg0KYGBge3J9DQpzZXBzaXMgJT4lDQogICAgdHJhY2VfZXhwbG9yZXIobl90cmFjZXMgPSAxMCwNCiAgICAgICAgICAgICAgICAgICBjb3ZlcmFnZV9sYWJlbHMgPSBjKCJjdW11bGF0aXZlIiwgInJlbGF0aXZlIikpDQpgYGANCg0KVGhlIGNvZGUgYHNlcHNpcyAlPiUgdHJhY2VfZXhwbG9yZXIobl90cmFjZXMgPSAxMCwgbGFiZWxfc2l6ZSA9IDQpYCBhbGxvd3MgbWUgdG8gZXhwbG9yZSB0aGUgZmlyc3QgMTAgdHJhY2VzIGluIHRoZSBzZXBzaXMgZGF0YXNldCB3aGlsZSBhZGp1c3RpbmcgdGhlIGxhYmVsIHNpemUgdG8gNCwgbWFraW5nIHRoZSB0cmFjZSBsYWJlbHMgbW9yZSByZWFkYWJsZSBmb3IgYmV0dGVyIGFuYWx5c2lzLg0KYGBge3J9DQpzZXBzaXMgJT4lDQogICAgdHJhY2VfZXhwbG9yZXIobl90cmFjZXMgPSAxMCwgbGFiZWxfc2l6ZSA9IDQpDQpgYGANCg0KVGhlIGNvZGUgYHNlcHNpcyAlPiUgdHJhY2VfZXhwbG9yZXIobl90cmFjZXMgPSAxMCwgc2hvd19sYWJlbHMgPSBGQUxTRSlgIGFsbG93cyBtZSB0byBleHBsb3JlIHRoZSBmaXJzdCAxMCB0cmFjZXMgaW4gdGhlIHNlcHNpcyBkYXRhc2V0IHdpdGhvdXQgZGlzcGxheWluZyB0aGUgbGFiZWxzLCBwcm92aWRpbmcgYSBjbGVhbmVyIHZpZXcgb2YgdGhlIHRyYWNlIHNlcXVlbmNlcy4NCmBgYHtyfQ0Kc2Vwc2lzICU+JQ0KICAgIHRyYWNlX2V4cGxvcmVyKG5fdHJhY2VzID0gMTAsIA0KICAgICAgICAgICAgICAgICAgIHNob3dfbGFiZWxzID0gRkFMU0UpDQpgYGANCg0KVGhlIGNvZGUgYHNlcHNpcyAlPiUgdHJhY2VfZXhwbG9yZXIobl90cmFjZXMgPSAxMCwgYWJicmV2aWF0ZSA9IEZBTFNFKWAgYWxsb3dzIG1lIHRvIGV4cGxvcmUgdGhlIGZpcnN0IDEwIHRyYWNlcyBpbiB0aGUgc2Vwc2lzIGRhdGFzZXQgd2l0aG91dCBhYmJyZXZpYXRpbmcgdGhlIGFjdGl2aXR5IGxhYmVscywgcHJvdmlkaW5nIGEgZnVsbCB2aWV3IG9mIHRoZSB0cmFjZSBkZXRhaWxzLg0KYGBge3J9DQpzZXBzaXMgJT4lDQogICAgdHJhY2VfZXhwbG9yZXIobl90cmFjZXMgPSAxMCwgYWJicmV2aWF0ZSA9IEZBTFNFKQ0KYGBgDQoNClRoZSBjb2RlIGBzZXBzaXMgJT4lIHRyYWNlX2V4cGxvcmVyKG5fdHJhY2VzID0gMTAsIHNjYWxlX2ZpbGwgPSBnZ3Bsb3QyOjpzY2FsZV9maWxsX2Rpc2NyZXRlKWAgYWxsb3dzIG1lIHRvIGV4cGxvcmUgdGhlIGZpcnN0IDEwIHRyYWNlcyBpbiB0aGUgc2Vwc2lzIGRhdGFzZXQsIGFwcGx5aW5nIGEgZGlzY3JldGUgY29sb3Igc2NhbGUgZnJvbSBnZ3Bsb3QyIHRvIGJldHRlciBkaWZmZXJlbnRpYXRlIHRoZSBhY3Rpdml0eSBsYWJlbHMuDQpgYGB7cn0NCnNlcHNpcyAlPiUNCiAgICB0cmFjZV9leHBsb3JlcihuX3RyYWNlcyA9IDEwLA0KICAgICAgICAgICAgICAgICAgIHNjYWxlX2ZpbGwgPSBnZ3Bsb3QyOjpzY2FsZV9maWxsX2Rpc2NyZXRlKQ0KYGBgDQoNCiMjIDQuOCBQZXJmb3JtYW5jZSBTcGVjdHJ1bQ0KVGhlIGNvZGUgYHRyYWZmaWNfZmluZXMgJT4lIHBzX2RldGFpbGVkKClgIGdlbmVyYXRlcyBhIGRldGFpbGVkIHByb2Nlc3Mgc3VtbWFyeSBvZiB0aGUgdHJhZmZpY19maW5lcyBkYXRhc2V0LCBwcm92aWRpbmcgYW4gaW4tZGVwdGggdmlldyBvZiB0aGUgcHJvY2VzcyBmbG93IGFuZCBpdHMgY2hhcmFjdGVyaXN0aWNzLg0KYGBge3J9DQp0cmFmZmljX2ZpbmVzICU+JQ0KICAgIHBzX2RldGFpbGVkKCkNCmBgYA0KDQpUaGUgY29kZSBgdHJhZmZpY19maW5lcyAlPiUgcHNfZGV0YWlsZWQobl9zZWdtZW50cyA9IDEwKWAgZ2VuZXJhdGVzIGEgZGV0YWlsZWQgcHJvY2VzcyBzdW1tYXJ5IG9mIHRoZSB0cmFmZmljX2ZpbmVzIGRhdGFzZXQsIGRpc3BsYXlpbmcgaW5mb3JtYXRpb24gZm9yIHRoZSBmaXJzdCAxMCBzZWdtZW50cyBvZiB0aGUgcHJvY2VzcyBmbG93Lg0KYGBge3J9DQp0cmFmZmljX2ZpbmVzICU+JQ0KICAgIHBzX2RldGFpbGVkKG5fc2VnbWVudHMgPSAxMCkNCmBgYA0KDQpUaGUgY29kZSBgdHJhZmZpY19maW5lcyAlPiUgcHNfZGV0YWlsZWQoY2xhc3NpZmljYXRpb24gPSAicmVzb3VyY2UiKWAgZ2VuZXJhdGVzIGEgZGV0YWlsZWQgcHJvY2VzcyBzdW1tYXJ5IG9mIHRoZSB0cmFmZmljX2ZpbmVzIGRhdGFzZXQsIGZvY3VzaW5nIG9uIHRoZSByZXNvdXJjZSBjbGFzc2lmaWNhdGlvbiB0byBwcm92aWRlIGluc2lnaHRzIGludG8gcmVzb3VyY2UgdXNhZ2Ugd2l0aGluIHRoZSBwcm9jZXNzLg0KYGBge3J9DQp0cmFmZmljX2ZpbmVzICU+JQ0KICAgIHBzX2RldGFpbGVkKGNsYXNzaWZpY2F0aW9uID0gInJlc291cmNlIikNCmBgYA0KVGhlIGNvZGUgYHRyYWZmaWNfZmluZXMgJT4lIGVuZF9hY3Rpdml0aWVzKCJjYXNlIikgJT4lIGF1Z21lbnQodHJhZmZpY19maW5lcywgcHJlZml4ID0gImVuZCIpICU+JSBwc19kZXRhaWxlZChjbGFzc2lmaWNhdGlvbiA9ICJlbmRfYWN0aXZpdHkiKWAgYW5hbHl6ZXMgdGhlIGVuZCBhY3Rpdml0aWVzIG9mIHRoZSB0cmFmZmljX2ZpbmVzIGRhdGFzZXQsIGF1Z21lbnRzIHRoZSBkYXRhIHdpdGggaW5mb3JtYXRpb24gb24gdGhlc2UgYWN0aXZpdGllcywgYW5kIGdlbmVyYXRlcyBhIGRldGFpbGVkIHByb2Nlc3Mgc3VtbWFyeSBmb2N1c2luZyBvbiB0aGUgY2xhc3NpZmljYXRpb24gb2YgZW5kIGFjdGl2aXRpZXMuDQpgYGB7cn0NCnRyYWZmaWNfZmluZXMgJT4lDQogICAgZW5kX2FjdGl2aXRpZXMoImNhc2UiKSAlPiUNCiAgICBhdWdtZW50KHRyYWZmaWNfZmluZXMsIHByZWZpeCA9ICJlbmQiKSAlPiUNCiAgICBwc19kZXRhaWxlZChjbGFzc2lmaWNhdGlvbiA9ICJlbmRfYWN0aXZpdHkiKQ0KYGBgDQoNClRoZSBjb2RlIGB0cmFmZmljX2ZpbmVzICU+JSBlbmRfYWN0aXZpdGllcygiY2FzZSIpICU+JSBhdWdtZW50KHRyYWZmaWNfZmluZXMsIHByZWZpeCA9ICJlbmQiKSAlPiUgZ3JvdXBfYnkoZW5kX2FjdGl2aXR5KSAlPiUgcHNfYWdncmVnYXRlZCgpYCBhbmFseXplcyB0aGUgZW5kIGFjdGl2aXRpZXMgb2YgdGhlIHRyYWZmaWNcX2ZpbmVzIGRhdGFzZXQsIGF1Z21lbnRzIHRoZSBkYXRhIHdpdGggdGhlc2UgYWN0aXZpdGllcywgZ3JvdXBzIHRoZSBkYXRhIGJ5IGVuZCBhY3Rpdml0eSwgYW5kIGdlbmVyYXRlcyBhbiBhZ2dyZWdhdGVkIHByb2Nlc3Mgc3VtbWFyeS4NCmBgYHtyfQ0KdHJhZmZpY19maW5lcyAlPiUNCiAgICBlbmRfYWN0aXZpdGllcygiY2FzZSIpICU+JQ0KICAgIGF1Z21lbnQodHJhZmZpY19maW5lcywgcHJlZml4ID0gImVuZCIpICU+JQ0KICAgIGdyb3VwX2J5KGVuZF9hY3Rpdml0eSkgJT4lDQogICAgcHNfYWdncmVnYXRlZCgpDQpgYGANCg0KIyA1LiBNb3JlIEFuYWx5dGljcw0KIyMgNS4xIENvbnRyb2wgRmxvdw0KIyMjIEFjdGl2aXR5IFByZXNlbmNlDQpUaGUgY29kZSBgcGF0aWVudHMgJT4lIGFjdGl2aXR5X3ByZXNlbmNlKCkgJT4lIHBsb3RgIHZpc3VhbGl6ZXMgdGhlIHBlcmNlbnRhZ2Ugb2YgY2FzZXMgaW4gd2hpY2ggZWFjaCBhY3Rpdml0eSBpcyBwcmVzZW50IGluIHRoZSBwYXRpZW50cyBkYXRhc2V0LCBwcm92aWRpbmcgYW4gb3ZlcnZpZXcgb2YgYWN0aXZpdHkgcHJlc2VuY2Ugd2l0aG91dCByZXF1aXJpbmcgYSBsZXZlbCBhcmd1bWVudC4NCmBgYHtyfQ0KcGF0aWVudHMgJT4lIGFjdGl2aXR5X3ByZXNlbmNlKCkgJT4lDQogICAgcGxvdA0KYGBgDQojIyMgQWN0aXZpdHkgZnJlcXVlbmN5DQpUaGUgY29kZSBgcGF0aWVudHMgJT4lIGFjdGl2aXR5X2ZyZXF1ZW5jeSgiYWN0aXZpdHkiKWAgY2FsY3VsYXRlcyB0aGUgZnJlcXVlbmN5IG9mIGVhY2ggYWN0aXZpdHkgaW4gdGhlIHBhdGllbnRzIGRhdGFzZXQsIHByb3ZpZGluZyBpbnNpZ2h0cyBpbnRvIGhvdyBvZnRlbiBkaWZmZXJlbnQgYWN0aXZpdGllcyBvY2N1ciB3aXRoaW4gdGhlIHByb2Nlc3MuDQpgYGB7cn0NCnBhdGllbnRzICU+JQ0KICAgIGFjdGl2aXR5X2ZyZXF1ZW5jeSgiYWN0aXZpdHkiKQ0KYGBgDQoNCiMjIyBTdGFydCBhY3Rpdml0aWVzDQpUaGUgY29kZSBgcGF0aWVudHMgJT4lIHN0YXJ0X2FjdGl2aXRpZXMoInJlc291cmNlLWFjdGl2aXR5IilgIGlkZW50aWZpZXMgdGhlIHN0YXJ0aW5nIGFjdGl2aXRpZXMgaW4gdGhlIHBhdGllbnRzIGRhdGFzZXQgYmFzZWQgb24gdGhlIHJlc291cmNlLWFjdGl2aXR5IGNsYXNzaWZpY2F0aW9uLCBoZWxwaW5nIHRvIGFuYWx5emUgdGhlIGluaXRpYWwgc3RlcHMgaW52b2x2aW5nIHNwZWNpZmljIHJlc291cmNlcy4NCmBgYHtyfQ0KcGF0aWVudHMgJT4lDQogICAgc3RhcnRfYWN0aXZpdGllcygicmVzb3VyY2UtYWN0aXZpdHkiKQ0KYGBgDQoNCiMjIyBFbmQgYWN0aXZpdGllcw0KVGhlIGNvZGUgYHBhdGllbnRzICU+JSBlbmRfYWN0aXZpdGllcygicmVzb3VyY2UtYWN0aXZpdHkiKWAgaWRlbnRpZmllcyB0aGUgZW5kIGFjdGl2aXRpZXMgaW4gdGhlIHBhdGllbnRzIGRhdGFzZXQgYmFzZWQgb24gdGhlIHJlc291cmNlLWFjdGl2aXR5IGNsYXNzaWZpY2F0aW9uLCBhbGxvd2luZyBtZSB0byBhbmFseXplIHRoZSBmaW5hbCBzdGVwcyBpbnZvbHZpbmcgc3BlY2lmaWMgcmVzb3VyY2VzLg0KYGBge3J9DQpwYXRpZW50cyAlPiUNCiAgICBlbmRfYWN0aXZpdGllcygicmVzb3VyY2UtYWN0aXZpdHkiKQ0KYGBgDQoNCiMjIyBUcmFjZSBDb3ZlcmFnZQ0KVGhlIGNvZGUgYHBhdGllbnRzICU+JSB0cmFjZV9jb3ZlcmFnZSgidHJhY2UiKSAlPiUgcGxvdCgpYCB2aXN1YWxpemVzIHRoZSBjb3ZlcmFnZSBvZiBkaWZmZXJlbnQgdHJhY2VzIGluIHRoZSBwYXRpZW50cyBkYXRhc2V0LCBwcm92aWRpbmcgaW5zaWdodHMgaW50byBob3cgd2VsbCB0aGUgdHJhY2VzIGFyZSByZXByZXNlbnRlZCB3aXRoaW4gdGhlIGRhdGEuDQpgYGB7cn0NCnBhdGllbnRzICU+JQ0KICAgIHRyYWNlX2NvdmVyYWdlKCJ0cmFjZSIpICU+JQ0KICAgIHBsb3QoKQ0KYGBgDQoNCiMjIyBUcmFuY2UgbGVuZ3RoDQpUaGUgY29kZSBgcGF0aWVudHMgJT4lIHRyYWNlX2xlbmd0aCgibG9nIikgJT4lIHBsb3RgIHZpc3VhbGl6ZXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0cmFjZSBsZW5ndGhzIGluIHRoZSBwYXRpZW50cyBkYXRhc2V0LCBoZWxwaW5nIHRvIGFuYWx5emUgdGhlIHZhcmlhYmlsaXR5IGluIHRoZSBudW1iZXIgb2YgYWN0aXZpdGllcyB3aXRoaW4gZWFjaCB0cmFjZS4NCmBgYHtyfQ0KcGF0aWVudHMgJT4lDQogICAgdHJhY2VfbGVuZ3RoKCJsb2ciKSAlPiUNCiAgICBwbG90DQpgYGANCg0KIyMgNS4yIFBlcmZvcm1hbmNlDQojIyMgSWRsZSBUaW1lDQpUaGUgY29kZSBgcGF0aWVudHMgJT4lIGlkbGVfdGltZSgicmVzb3VyY2UiLCB1bml0cyA9ICJkYXlzIilgIGNhbGN1bGF0ZXMgdGhlIGlkbGUgdGltZSBmb3IgZWFjaCByZXNvdXJjZSBpbiB0aGUgcGF0aWVudHMgZGF0YXNldCwgbWVhc3VyaW5nIHRoZSB0aW1lIGluIGRheXMgd2hlbiByZXNvdXJjZXMgd2VyZSBub3QgaW4gdXNlLg0KYGBge3J9DQpwYXRpZW50cyAlPiUNCiAgICBpZGxlX3RpbWUoInJlc291cmNlIiwgdW5pdHMgPSAiZGF5cyIpDQpgYGANCg0KVGhlIGNvZGUgYHBhdGllbnRzICU+JSBpZGxlX3RpbWUoInJlc291cmNlIiwgdW5pdHMgPSAiZGF5cyIpICU+JSBwbG90KClgIHZpc3VhbGl6ZXMgdGhlIGlkbGUgdGltZSBvZiByZXNvdXJjZXMgaW4gdGhlIHBhdGllbnRzIGRhdGFzZXQsIHNob3dpbmcgaG93IG1hbnkgZGF5cyBlYWNoIHJlc291cmNlIHdhcyBpbmFjdGl2ZS4NCmBgYHtyfQ0KcGF0aWVudHMgJT4lDQogICAgaWRsZV90aW1lKCJyZXNvdXJjZSIsIHVuaXRzID0gImRheXMiKSAlPiUNCiAgICBwbG90KCkNCmBgYA0KDQojIyMgUHJvY2Vzc2luZyBUaW1lDQpUaGUgY29kZSBgcGF0aWVudHMgJT4lIHByb2Nlc3NpbmdfdGltZSgiYWN0aXZpdHkiKSAlPiUgcGxvdGAgdmlzdWFsaXplcyB0aGUgcHJvY2Vzc2luZyB0aW1lIGZvciBlYWNoIGFjdGl2aXR5IGluIHRoZSBwYXRpZW50cyBkYXRhc2V0LCBwcm92aWRpbmcgaW5zaWdodHMgaW50byB0aGUgZHVyYXRpb24gb2YgZGlmZmVyZW50IGFjdGl2aXRpZXMgd2l0aGluIHRoZSBwcm9jZXNzLg0KYGBge3J9DQpwYXRpZW50cyAlPiUgDQogICAgcHJvY2Vzc2luZ190aW1lKCJhY3Rpdml0eSIpICU+JQ0KICAgIHBsb3QNCmBgYA0KDQojIyMgVGhyb3VnaHB1dCBUaW1lDQpUaGUgY29kZSBgcGF0aWVudHMgJT4lIHRocm91Z2hwdXRfdGltZSgibG9nIikgJT4lIHBsb3QoKWAgdmlzdWFsaXplcyB0aGUgdGhyb3VnaHB1dCB0aW1lIGluIHRoZSBwYXRpZW50cyBkYXRhc2V0LCBkaXNwbGF5aW5nIHRoZSB0aW1lIHRha2VuIGZvciBjYXNlcyB0byBtb3ZlIHRocm91Z2ggdGhlIGVudGlyZSBwcm9jZXNzLg0KYGBge3J9DQpwYXRpZW50cyAlPiUNCiAgICB0aHJvdWdocHV0X3RpbWUoImxvZyIpICU+JQ0KICAgIHBsb3QoKQ0KYGBgDQoNCiMjIDUuMyBPcmdhbmlzYXRpb25hbA0KIyMjIFJlc291cmNlIEZyZXF1ZW5jeQ0KVGhlIGNvZGUgYHBhdGllbnRzICU+JSByZXNvdXJjZV9mcmVxdWVuY3koInJlc291cmNlIilgIGNhbGN1bGF0ZXMgdGhlIGZyZXF1ZW5jeSBvZiBlYWNoIHJlc291cmNlIGluIHRoZSBwYXRpZW50cyBkYXRhc2V0LCBzaG93aW5nIGhvdyBvZnRlbiBkaWZmZXJlbnQgcmVzb3VyY2VzIGFyZSB1dGlsaXplZCB0aHJvdWdob3V0IHRoZSBwcm9jZXNzLg0KYGBge3J9DQpwYXRpZW50cyAlPiUNCiAgICByZXNvdXJjZV9mcmVxdWVuY3koInJlc291cmNlIikNCmBgYA0KDQojIyMgUmVzb3VyY2UgSW52b2x2bWVudA0KVGhlIGNvZGUgYHBhdGllbnRzICU+JSByZXNvdXJjZV9pbnZvbHZlbWVudChsZXZlbCA9ICJyZXNvdXJjZSIpICU+JSBwbG90YCB2aXN1YWxpemVzIHRoZSBpbnZvbHZlbWVudCBvZiBlYWNoIHJlc291cmNlIGluIHRoZSBwYXRpZW50cyBkYXRhc2V0LCBoaWdobGlnaHRpbmcgaG93IGZyZXF1ZW50bHkgZGlmZmVyZW50IHJlc291cmNlcyBwYXJ0aWNpcGF0ZSBpbiB0aGUgcHJvY2Vzcy4NCg0KSXQgdGhpcyBleGFtcGxlIGl0IHNob3dzIHRoYXQgb25seSByMSBhbmQgcjIgYXJlIGludm9sdmVkIGluIGFsbCBjYXNlcywgcjYgYW5kIHI3IGFyZSBpbnZvbHZlZCBpbiBtb3N0IG9mIHRoZSBjYXNlcywgd2hpbGUgdGhlIG90aGVycyBhcmUgb25seSBpbnZvbHZlZCBpbiBoYWxmIG9mIHRoZSBjYXNlcywgbW9yZSBvciBsZXNzLg0KYGBge3J9DQpwYXRpZW50cyAlPiUNCiAgICByZXNvdXJjZV9pbnZvbHZlbWVudChsZXZlbCA9ICJyZXNvdXJjZSIpICU+JSBwbG90DQpgYGANCg0KIyMjIFJlc291cmNlIFNwZWNpYWxpemF0aW9uDQpUaGUgY29kZSBgcGF0aWVudHMgJT4lIHJlc291cmNlX3NwZWNpYWxpc2F0aW9uKCJyZXNvdXJjZSIpYCBhbmFseXplcyB0aGUgc3BlY2lhbGl6YXRpb24gb2YgZWFjaCByZXNvdXJjZSBpbiB0aGUgcGF0aWVudHMgZGF0YXNldCwgc2hvd2luZyB0aGUgc3BlY2lmaWMgYWN0aXZpdGllcyBvciB0YXNrcyB0aGF0IGVhY2ggcmVzb3VyY2UgaXMgbW9zdCBmcmVxdWVudGx5IGludm9sdmVkIGluLg0KDQpJbiB0aGUgc2ltcGxlIHBhdGllbnRzIGV2ZW50IGxvZywgZWFjaCByZXNvdXJjZSBpcyBwZXJmb3JtaW5nIGV4YWN0bHkgb25lIGFjdGl2aXR5LCBhbmQgaXMgdGhlcmVmb3JlIDEwMCUgc3BlY2lhbGl6ZWQuDQpgYGB7cn0NCnBhdGllbnRzICU+JQ0KICAgIHJlc291cmNlX3NwZWNpYWxpc2F0aW9uKCJyZXNvdXJjZSIpDQpgYGANCg0KIyMjIEhhbmRvdmVyLW9mLXdvcmsgbmV0d29yaw0KVGhlIGNvZGUgYHBhdGllbnRzICU+JSByZXNvdXJjZV9tYXAoKWAgZ2VuZXJhdGVzIGEgcmVzb3VyY2UgbWFwIG9mIHRoZSBwYXRpZW50cyBkYXRhc2V0LCB2aXN1YWxseSBkaXNwbGF5aW5nIGhvdyByZXNvdXJjZXMgYXJlIGRpc3RyaWJ1dGVkIGFuZCBpbnZvbHZlZCBhY3Jvc3MgZGlmZmVyZW50IGFjdGl2aXRpZXMgaW4gdGhlIHByb2Nlc3MuDQpgYGB7cn0NCnBhdGllbnRzICU+JQ0KICAgIHJlc291cmNlX21hcCgpDQpgYGANCg0KIyMjIFJlc291cmNlIHByZWNlZGVuY2UgbWF0cml4DQpUaGUgY29kZSBgcGF0aWVudHMgJT4lIHJlc291cmNlX21hdHJpeCgpICU+JSBwbG90KClgIGdlbmVyYXRlcyBhbmQgdmlzdWFsaXplcyBhIHJlc291cmNlIG1hdHJpeCBmb3IgdGhlIHBhdGllbnRzIGRhdGFzZXQsIHNob3dpbmcgdGhlIGludGVyYWN0aW9ucyBiZXR3ZWVuIHJlc291cmNlcyBhbmQgYWN0aXZpdGllcyB3aXRoaW4gdGhlIHByb2Nlc3MuDQpgYGB7cn0NCnBhdGllbnRzICU+JQ0KICAgIHJlc291cmNlX21hdHJpeCgpICU+JQ0KICAgIHBsb3QoKQ0KYGBgDQoNCiMjIDUuNCBNdWx0aS1kaW1lbnNpb25hbA0KIyMjIFcgTyBSIEsgLSBJIE4gLSBQIFIgTyBHIFIgRSBTIFMNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=